package top.szhome.framework.core.tools.util;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.StringJoiner;

/**
 * 字符串工具类
 *
 * @author 唐加利
 * @date 2023/7/23
 **/
public final class StringUtil {

    /**
     * 空字符串
     */
    private static final String EMPTY = "";

    /**
     * 字符串Builder初始化长度
     */
    private static final int STRING_BUILDER_SIZE = 256;

    /**
     * 获取字符串的长度
     * @param str
     * @return
     */
    public static int length(CharSequence str){
        return str == null ? 0 : str.length();
    }

    /**
     * 字符串是否为空
     * @param str
     * @return
     */
    public static boolean isBlank(CharSequence str){
        int len = length(str);
        if(len == 0){
            return true;
        }

        for(int i = 0; i < len; ++i) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * 构造一个字符重复指定次数的字符串
     * @param ch        字符
     * @param repeat    重复次数
     * @return  返回字符重复指定次数的字符串
     */
    public static String repeat(char ch, int repeat) {
        if (repeat <= 0) {
            return "";
        }

        char[] buf = new char[repeat];
        Arrays.fill(buf, ch);
        return new String(buf);
    }

    /**
     * 字符串重复
     * @param str   字符串
     * @param times 重复次数
     * @return
     */
    public static String repeat(String str, int times){
        if(str == null){
            return null;
        }

        if(times <= 0){
            return EMPTY;
        }

        if(times == 1 || str.length() == 0){
            return str;
        }

        final StringBuilder buf = new StringBuilder(times * str.length());
        for (int i = 0; i < times; i++) {
            buf.append(str);
        }
        return buf.toString();
    }

    /**
     * 拼接字符串
     * @param strings   字符串数组
     * @param delimiter 分隔符
     * @return
     */
    public static String join(String[] strings, char delimiter) {
        return join(strings, String.valueOf(delimiter));
    }

    /**
     * 拼接字符串
     * @param strings   字符串数组
     * @param delimiter 分隔符
     * @return
     */
    public static String join(String[] strings, String delimiter) {
        if(strings == null){
            return null;
        }

        final StringJoiner joiner = new StringJoiner(delimiter);
        for(String str : strings){
            joiner.add(str);
        }
        return joiner.toString();
    }

    /**
     * 拼接对象为字符串
     * @param objects   对象集合
     * @param delimiter 分隔符
     * @return 返回分隔符拼接的字符串
     */
    public static String join(List<?> objects, String delimiter) {
        if (objects == null) {
            return null;
        }

        return join(objects.iterator(), delimiter);
    }

    /**
     * 拼接迭代器为字符串
     * @param iterator  迭代器
     * @param delimiter 分隔符
     * @return 返回分隔符拼接的字符串
     */
    private static String join(Iterator<?> iterator, String delimiter) {
        if (iterator == null) {
            return null;
        }

        if (!iterator.hasNext()) {
            return EMPTY;
        }

        final Object first = iterator.next();
        if (!iterator.hasNext()) {
            return first == null ? EMPTY : String.valueOf(first);
        }

        // two or more elements，Java default is 16, probably too small
        final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE);
        if (first != null) {
            buf.append(first);
        }

        while (iterator.hasNext()) {
            buf.append(delimiter);
            final Object obj = iterator.next();
            if (obj != null) {
                buf.append(obj);
            }
        }

        return buf.toString();
    }

    /**
     * 首字母转大写
     * @param str   字符串
     * @return  首字母转大写的字符串
     */
    public static String capitalize(String str){
        final int strLen = length(str);
        if (strLen == 0) {
            return str;
        }

        final int firstCodepoint = str.codePointAt(0);
        final int newCodePoint = Character.toTitleCase(firstCodepoint);
        if (firstCodepoint == newCodePoint) {
            // already capitalized
            return str;
        }

        // cannot be longer than the char array
        final int[] newCodePoints = new int[strLen];
        int outOffset = 0;
        // copy the first codepoint
        newCodePoints[outOffset++] = newCodePoint;
        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
            final int codepoint = str.codePointAt(inOffset);
            // copy the remaining ones
            newCodePoints[outOffset++] = codepoint;
            inOffset += Character.charCount(codepoint);
        }
        return new String(newCodePoints, 0, outOffset);
    }

    /**
     * 检测字符串是否有指定前缀
     * @param str
     * @param prefix
     * @return
     */
    public static boolean startsWith(String str, String prefix){
        return str == null ? false : str.startsWith(prefix);
    }

    /**
     * 检测字符串是否有指定后缀
     * @param str
     * @param suffix
     * @return
     */
    public static boolean endsWith(String str, String suffix){
        return str == null ? false : str.endsWith(suffix);
    }

}
